#include <chrono>
#include <iostream>
#include <vector>
#include <iomanip>
#include <random>
#include <thread>

#include "../code/ThreeLayersMemoryPool.hpp"

// 计时器类
class Timer
{
    std::chrono::high_resolution_clock::time_point start;

public:
    Timer() : start(std::chrono::high_resolution_clock::now()) {}

    double elapsed()
    {
        auto end = std::chrono::high_resolution_clock::now();
        return std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() / 1000.0; // 转换为毫秒
    }
};

// 性能测试类
class PerformanceTest
{
private:
    // 测试统计信息
    // struct TestStats
    // {
    //     double systemCallTime{0.0}; // 系统调用耗时
    //     double memoryPoolTime{0.0}; // 内存池耗时
    //     size_t totalAllocs{0};      // 总分配次数
    //     size_t totalBytes{0};       // 总分配字节数
    // };

public:
    // 1. 系统预热
    static void warmup()
    {
        std::cout << "Warming up memory systems...\n";

        std::vector<std::pair<void *, size_t>> allocs; // 地址-大小，用于释放

        // 分配
        for (int i = 0; i < 1000; ++i)
        {
            for (const size_t size : {32, 64, 128, 256, 512})
            {
                void *ptr = MemoryPool::ThreeLayersMemoryPool::alloc(size);
                allocs.emplace_back(ptr, size);
            }
        }

        // 释放
        for (const auto &pair : allocs) // 可以用C++17的结构化绑定：const auto &[p, sz] : allocs
        {
            MemoryPool::ThreeLayersMemoryPool::dealloc(pair.first, pair.second);
        }

        std::cout << "Warmup complete.\n\n";
    }

    // 2. 小对象分配测试
    static void testSmallAllocation()
    {
        // 大分配释放次数，可能内存池要维护数据结构导致性能不佳
        // constexpr size_t ALLOC_NUM = 1000000;
        // constexpr size_t SMALL_SIZE = 32;
        constexpr size_t ALLOC_NUM = 70;
        constexpr size_t SMALL_SIZE = 32;

        std::cout << "\nTesting small allocations (" << ALLOC_NUM << " allocations of "
                  << SMALL_SIZE << " bytes):" << std::endl;

        // 测试new/delete
        // {}作用域妙用
        {
            Timer t{}; // 开始计时

            std::vector<void *> ptrs{};
            ptrs.reserve(ALLOC_NUM);
            // std::vector<void *> ptrs(ALLOC_NUM);

            for (size_t i = 0; i < ALLOC_NUM; ++i)
            {
                // ptrs.push_back(new char[SMALL_SIZE]);
                ptrs.emplace_back(new char[SMALL_SIZE]);

                // 模拟真实使用：部分立即释放
                if (i % 4 == 0)
                {
                    delete[] static_cast<char *>(ptrs.back());
                    ptrs.pop_back();
                }
            }

            // 全部释放
            for (void *ptr : ptrs)
            {
                delete[] static_cast<char *>(ptr);
            }

            std::cout << "New/Delete: " << std::fixed << std::setprecision(3)
                      << t.elapsed() << " ms" << std::endl;
        }

        // 测试内存池
        {
            Timer t{};

            std::vector<void *> ptrs{};
            ptrs.reserve(ALLOC_NUM);

            for (size_t i = 0; i < ALLOC_NUM; ++i)
            {
                ptrs.emplace_back(MemoryPool::ThreeLayersMemoryPool::alloc(SMALL_SIZE));

                if (i % 4 == 0)
                {
                    MemoryPool::ThreeLayersMemoryPool::dealloc(ptrs.back(), SMALL_SIZE);
                    ptrs.pop_back();
                }
            }

            for (void *ptr : ptrs)
            {
                MemoryPool::ThreeLayersMemoryPool::dealloc(ptr, SMALL_SIZE);
            }

            std::cout << "Memory Pool: " << std::fixed << std::setprecision(3)
                      << t.elapsed() << " ms" << std::endl;
        }
    }

    // 3. 多线程测试
    static void testMultiThread()
    {
        constexpr size_t THREAD_NUM = 4;
        constexpr size_t PER_THREAD_ALLOC = 25000;
        constexpr size_t MAX_ALLOC_SIZE = 256;

        std::cout << "\nTesting multi-threaded allocations (" << THREAD_NUM << " threads, "
                  << PER_THREAD_ALLOC << " allocations each):" << std::endl;

        auto threadFunc = [](bool useMemoryPool)
        {
            std::random_device rd{};
            std::mt19937 gen(rd());
            std::uniform_int_distribution<> dis(8, MAX_ALLOC_SIZE); // 最小字节对齐数8-256 均匀分布的随机整数

            std::vector<std::pair<void *, size_t>> ptrs{};
            ptrs.reserve(PER_THREAD_ALLOC);

            for (size_t i = 0; i < PER_THREAD_ALLOC; ++i)
            {
                size_t size = dis(gen);
                void *ptr = useMemoryPool ? MemoryPool::ThreeLayersMemoryPool::alloc(size) : new char[size];
                ptrs.push_back({ptr, size});

                // 随机释放一些内存
                if (rand() % 100 < 75) // 75%的概率释放
                {
                    size_t index = rand() % ptrs.size();
                    if (useMemoryPool)
                    {
                        MemoryPool::ThreeLayersMemoryPool::dealloc(ptrs[index].first, ptrs[index].second);
                    }
                    else
                    {
                        delete[] static_cast<char *>(ptrs[index].first);
                    }

                    ptrs[index] = ptrs.back(); // 注意，数组不是链表只能覆盖不能删除，最后一个补充，删除最后一个
                    ptrs.pop_back();
                }
            }

            // 清理剩余内存
            for (const auto &pair : ptrs)
            {
                if (useMemoryPool)
                {
                    MemoryPool::ThreeLayersMemoryPool::dealloc(pair.first, pair.second);
                }
                else
                {
                    delete[] static_cast<char *>(pair.first);
                }
            }
        };

        // 测试new/delete
        {
            Timer t{};
            std::vector<std::thread> threads{};

            for (size_t i = 0; i < THREAD_NUM; ++i)
            {
                threads.emplace_back(threadFunc, false);
            }

            for (auto &thread : threads)
            {
                thread.join();
            }

            std::cout << "New/Delete: " << std::fixed << std::setprecision(3)
                      << t.elapsed() << " ms" << std::endl;
        }

        // 测试内存池
        {
            Timer t{};
            std::vector<std::thread> threads{};

            for (size_t i = 0; i < THREAD_NUM; ++i)
            {
                threads.emplace_back(threadFunc, true);
            }

            for (auto &thread : threads)
            {
                thread.join();
            }

            std::cout << "Memory Pool: " << std::fixed << std::setprecision(3)
                      << t.elapsed() << " ms" << std::endl;
        }
    }

    // 4. 混合大小测试
    static void testMixedSize()
    {
        // 大分配释放次数，可能内存池要维护数据结构导致性能不佳
        // 大分配数，可能内存池要维护数据结构导致+再申请系统导致性能不佳
        // const size_t ALLOC_NUM = 50000;
        // const size_t MIXED_SIZES[] = {16, 32, 64, 128, 256, 512, 1024, 2048};
        const size_t ALLOC_NUM = 1000;
        const size_t MIXED_SIZES[] = {8, 16, 32, 64, 128, 256};

        std::cout << "\nTesting mixed size allocations (" << ALLOC_NUM << " allocations):" << std::endl;

        // 测试new/delete
        {
            Timer t{};

            std::vector<std::pair<void *, size_t>> ptrs{};
            ptrs.reserve(ALLOC_NUM);

            for (size_t i = 0; i < ALLOC_NUM; ++i)
            {
                size_t size = MIXED_SIZES[rand() % 8];
                void *ptr = new char[size];
                ptrs.emplace_back(ptr, size);

                if (i % 100 == 0 && !ptrs.empty())
                {
                    size_t releaseCount = std::min(ptrs.size(), size_t(20)); // 最多释放20个或剩余的
                    for (size_t j = 0; j < releaseCount; ++j)
                    {
                        delete[] static_cast<char *>(ptrs.back().first);
                        ptrs.pop_back();
                    }
                }
            }

            for (const auto &pair : ptrs)
            {
                delete[] static_cast<char *>(pair.first);
            }

            std::cout << "New/Delete: " << std::fixed << std::setprecision(3)
                      << t.elapsed() << " ms" << std::endl;
        }

        // 测试内存池
        {
            Timer t{};

            std::vector<std::pair<void *, size_t>> ptrs;
            ptrs.reserve(ALLOC_NUM);

            for (size_t i = 0; i < ALLOC_NUM; ++i)
            {
                size_t size = MIXED_SIZES[rand() % 8];
                void *ptr = MemoryPool::ThreeLayersMemoryPool::alloc(size);
                ptrs.emplace_back(ptr, size);

                if (i % 100 == 0 && !ptrs.empty())
                {
                    size_t releaseCount = std::min(ptrs.size(), size_t(20));
                    for (size_t j = 0; j < releaseCount; ++j)
                    {
                        MemoryPool::ThreeLayersMemoryPool::dealloc(ptrs.back().first, ptrs.back().second);
                        ptrs.pop_back();
                    }
                }
            }
            for (const auto &pair : ptrs)
            {
                MemoryPool::ThreeLayersMemoryPool::dealloc(pair.first, pair.second);
            }

            std::cout << "Memory Pool: " << std::fixed << std::setprecision(3)
                      << t.elapsed() << " ms" << std::endl;
        }
    }
};

int main()
{
    std::cout << "Starting performance tests..." << std::endl;

    // 预热系统
    PerformanceTest::warmup();

    // 运行测试
    PerformanceTest::testSmallAllocation();
    PerformanceTest::testMultiThread();
    PerformanceTest::testMixedSize();

    return 0;
}